import 'dart:async';

import 'package:annotation_route/route.dart';
import 'package:dk_flutter_base/dk_core.dart';
import 'package:dk_flutter_base/dk_ui.dart';
import 'package:flutter/foundation.dart';

typedef String SchemeFilter();
typedef Widget DefaultPageBuilder(String pageName);
///app运行环境标识
///* DEBUG 开发环境
///* COMMIT_TEST 测试环境
///* PRE_RELEASE 预发布环境
///* RELEASE 线上环境
enum EnvType {
  DEBUG,
  COMMIT_TEST,
  PRE_RELEASE,
  RELEASE,
}

///app运行环境配置
///* 利用对象实例化的生命周期，在main函数中通过实例化该对象，运行runApp()，简化main函数，理论上应该按照[EnvType]实例化不同的对象
///* value:运行环境全局实例
///* type:运行环境标识
///* application:设计初衷是参考Android，为了在该接口中实例化额外的sdk或者处理
///* materialAppParam:app全局样式配置
///* logicPageConfig:逻辑页面，logicPage全局配置
///* netWorkConfig:网络相关全局配置
///* routeIml:使用了阿里闲鱼的annotation_route库，模仿Android中的Arouter标注界面路由,该配置包含了自动生成的路由信息，用以自动化注册
///* schemeNativeFilterName:flutter中的Native界面的路由过滤符，默认为 dkflutter://
///* schemeFlutterFilterName:flutter中界面的路由过滤符，默认为 dkwidget://
///* screenAdaptConfig:屏幕适配全局配置参考[AdapterContainer]
///* appStateLifeCycle:flutter_boost容器的生命周期代理类
///* dkAppBarGlobalParams:appBar全局配置，由于flutter中的library库中的图片无法拉取到项目中，因此appBar组件需要该参数
class Env {
  static Env value;
  EnvType type = EnvType.DEBUG;
  Application application;

  MaterialAppParam materialAppParam;
  LogicPageConfig logicPageConfig;
  NetWorkConfig netWorkConfig;
  ARouterInternal routeIml;
  String schemeNativeFilterName;
  String schemeFlutterFilterName;
  ScreenAdaptConfig screenAdaptConfig;
  AppStateLifeCycle appStateLifeCycle;
  DkAppBarGlobalParams dkAppBarGlobalParams;

  Env(
      {this.type,
      this.routeIml,
      this.application,
      this.materialAppParam,
      this.logicPageConfig,
      this.netWorkConfig,
      this.schemeNativeFilterName,
      this.schemeFlutterFilterName,
      this.screenAdaptConfig,
      this.appStateLifeCycle,
      this.dkAppBarGlobalParams}) {
    value = this;
    value.schemeNativeFilterName ??= "dkflutter://";
    value.schemeFlutterFilterName ??= "dkwidget://";
    _init();
  }

  DefaultPageBuilder defaultPageBuilder;
  void registerDefaultPageBuilder(DefaultPageBuilder builder) {
    defaultPageBuilder = builder;
  }

  ///app真正初始化的地方
  ///* 执行了application中onCreate
  ///* 替换了FlutterError.onError，更改了flutter错误输出，默认DEBUG环境输出到控制台，其他情况被捕捉默认携带错误信息走路由，参考[handleError]路由格式为：dkflutter://error?error=""&stackTrace=""
  ///* 将整个flutterApp包裹在Zone中，并捕获异常
  ///* 根据runApp的实现，修改配置实现屏幕适配
  void _init() async {
    application = application ?? DefaultApplication();
    application?.onCreate();
    FlutterError.onError = (FlutterErrorDetails details) async {
      if (value?.type == EnvType.DEBUG) {
        FlutterError.dumpErrorToConsole(details);
      } else {
        Zone.current.handleUncaughtError(details.exception, details.stack);
      }
    };
    runZoned<Future<Null>>(() async {
      var screenAdaptConfig = Env?.value?.screenAdaptConfig;
      if (null == screenAdaptConfig) {
        Env?.value?.screenAdaptConfig = ScreenAdaptConfig(750, 1334);
      }
      InnerWidgetsFlutterBinding.ensureInitialized()
        ..attachRootWidget(ContainerApp(appStateLifeCycle))
        ..scheduleWarmUpFrame();
//      runApp(ContainerApp(appStateLifeCycle));
    }, onError: (error, stackTrace) async {
      handleError(error, stackTrace);
    });
    //设置透明状态栏
    /*SystemUiOverlayStyle systemUiOverlayStyle =
        SystemUiOverlayStyle(statusBarColor: Colors.transparent);
    SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);*/
  }

  ///处理捕获到的错误信息
  void handleError(error, stackTrace) async {
    RouteUtil.goPage("dkflutter://error?" +
        "error=${error?.toString() ?? ""}+&stackTrace=${stackTrace?.toString() ?? ""}");
  }

  ///由于每个环境实例可能有各自的特殊配置，通过基类提供通用方法交由子类实现，通过key-value的形式存储和获取
  dynamic getExtent(dynamic key) {
    return null;
  }

  ///设置环境实例的特殊配置，通过key-value的形式存储和获取
  void setExtent(dynamic key, dynamic extentObj) {}
}

///app全局样式配置
class MaterialAppParam {
  ThemeData themeData;
  TransitionBuilder builder;

  MaterialAppParam({this.themeData, this.builder});
}

///默认替换flutter全局的错误界面，样式参考[DkErrorWidget]，区分环境展示不同的样式
class DefaultApplication extends Application {
  @override
  void onCreate() {
    ErrorWidget.builder = (FlutterErrorDetails details) {
      return DkErrorWidget(ErrorOption.systemError(details));
    };
  }

  @override
  void onTerminate() {}
}
